 1.Spark Core之RDD编程中Action
   
   Action 用来触发RDD的计算，得到相关计算结果；
        Action触发Job。一个Spark程序(Driver程序)包含了多少 Action 算子，那么
就有多少Job；
        典型的Action算子: collect / count
        collect() => sc.runJob() => ... => dagScheduler.runJob() => 触发了Job
        要求：能快速准确的区分：Transformation、Action
   
   collect() / collectAsMap()
   stats / count / mean / stdev / max / min
   reduce(func) / fold(func) / aggregate(func)
   first()：Return the first element in this RDD
   take(n)：Take the first num elements of the RDD
   top(n)：按照默认（降序）或者指定的排序规则，返回前num个元素。
   takeSample(withReplacement, num, [seed])：返回采样的数据
   foreach(func) / foreachPartition(func)：与map、mapPartitions类似，区别是
foreach是 Action
   saveAsTextFile(path) / saveAsSequenceFile(path) / saveAsObjectFile(path)
   
// 返回统计信息。仅能作用 RDD[Double] 类型上调用
val rdd1 = sc.range(1, 101)
rdd1.stats

val rdd2 = sc.range(1, 101)

// 不能调用
rdd1.zip(rdd2).stats

// count在各种类型的RDD上，均能调用
rdd1.zip(rdd2).count

// 聚合操作
val rdd = sc.makeRDD(1 to 10, 2)
rdd.reduce(_+_)
rdd.fold(0)(_+_)
rdd.fold(1)(_+_)
rdd.fold(1)((x, y) => {
println(s"x=$x, y=$y")
x+y
})

rdd.aggregate(0)(_+_, _+_)
rdd.aggregate(1)(_+_, _+_)
rdd.aggregate(1)(
(a, b) => {
println(s"a=$a, b=$b")
a+b
},
(x, y) => {
println(s"x=$x, y=$y")
x+y
})

// first / take(n) / top(n) ：获取RDD中的元素。多用于测试
rdd.first
rdd.take(10)
rdd.top(10)

// 采样并返回结果
rdd.takeSample(false, 5)

rdd.foreach(x=>println(x+1))

// 保存文件到指定路径(rdd有多少分区，就保存为多少文件，保存文件时注意小文件问题)
rdd.saveAsTextFile("data/t1")
   